package org.openbpm.bus.api.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.sys.util.DbUtil;
import org.openbpm.base.core.id.IdUtil;
import org.openbpm.bpm.core.manager.BpmDefinitionManager;
import org.openbpm.bus.manager.BusColumnCtrlManager;
import org.openbpm.bus.manager.BusinessColumnManager;
import org.openbpm.bus.manager.BusinessObjectManager;
import org.openbpm.bus.manager.BusinessTableManager;
import org.openbpm.bus.model.*;
import org.openbpm.bus.model.xml.BusColumnXml;
import org.openbpm.bus.model.xml.BusTableXml;
import org.openbpm.bus.model.xml.BusinessObjectXml;
import org.openbpm.bus.model.xml.BusinessObjectXmlList;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service("etechBusinessObjectService")
public class EtechBusinessObjectService {
    @Resource
    BpmDefinitionManager bpmDefinitionManager;
    @Resource
    BusinessObjectManager businessObjectManager;
    @Resource
    BusinessTableManager businessTableManager;
    @Resource
    BusinessColumnManager businessColumnManager;
    @Resource
    BusColumnCtrlManager busColCtrlManager;


    public Map<String, String> exportBusObject(String... objIds) throws Exception{
        Map<String, String> exportFiles = new HashMap<String, String>();
        BusinessObjectXmlList xmlList = new BusinessObjectXmlList();
        for(String objId: objIds){
            BusinessObject businessObject = businessObjectManager.get(objId);
            BusinessObjectXml businessObjectXml  = new BusinessObjectXml(businessObject);
            // relationJson
            BusTableRel rel =  businessObject.getRelation();
            String relationJson = JSON.toJSONString(rel);
            businessObjectXml.setRelationJson(relationJson);
            // busTable
            Set<String> setTableKey = new HashSet<String>();
            for (BusTableRel rel2 : rel.list()) {
                setTableKey.add(rel2.getTableKey());
            }
            for (String tableKey : setTableKey) {
                BusinessTable businessTable =  this.businessTableManager.getFilledByKey(tableKey);
                if(businessTable!=null){
                    BusTableXml busTableXml = new BusTableXml(businessTable);
                    businessObjectXml.getBusTableList().add(busTableXml);
                }
            }

            xmlList.getBusinessObjectList().add(businessObjectXml);
        }
        String xml = org.openbpm.base.core.util.XmlCovertUtil.covert2Xml(xmlList);
        exportFiles.put("businessObject.xml", xml);
        return exportFiles;
    }

    public List<Map<String, Object>> importPreview(String busXml) throws Exception{

        List<Map<String, Object>> resultList = new ArrayList();

        BusinessObjectXmlList businessObjectXmlList = org.openbpm.base.core.util.XmlCovertUtil.covert2Object(busXml, new Class[]{BusinessObjectXmlList.class});
        for(BusinessObjectXml businessObjectXml: businessObjectXmlList.getBusinessObjectList()){
            Map<String, Object> map = new HashMap();


            map.put("busObjectExport", businessObjectXml);
            // busTableNames 导入涉及到table
            String busTableNames = "";
            //map.put("busTableExport", businessObjectXml.getBusTableList());
            for(BusTableXml busTableXml: businessObjectXml.getBusTableList()){
                if(!"".equals(busTableNames)){
                    busTableNames += ";";
                }
                busTableNames += busTableXml.getComment()+"("+busTableXml.getKey()+")";
            }
            map.put("busTableNames",busTableNames);
            //JSONObject relation = JSONObject.parseObject(businessObjectXml.getRelationJson());
            //map.put("relation",relation);

            // formNames  导入后影响到form
            String sql="select key_ from form_def where bo_key_ =?";
            List<Map<String, Object>> list = DbUtil.getJdbcTemplate().queryForList(sql, businessObjectXml.getKey());
            List<String> formNames=new ArrayList<>();
            for (Map<String, Object> stringObjectMap : list) {
                String key_ = MapUtil.getStr(stringObjectMap, "key_");
                formNames.add(key_);
            }
            map.put("formNames",formNames);
            resultList.add(map);
        }
        return resultList;
    }

    public void importSave(List<JSONObject> overViewList){
        for(JSONObject json: overViewList){
            // 1. get BusinessObjectXml
            JSONObject busObjectJson = json.getJSONObject("busObjectExport");
            BusinessObjectXml businessObjectXml = JSON.toJavaObject(busObjectJson, BusinessObjectXml.class);

            // 2. save BusinessObject & relation
            BusinessObject businessObject = businessObjectManager.getByKey(businessObjectXml.getKey());
            if(businessObject==null){
                businessObject = new BusinessObject();
            }else{
                fill(businessObject);
            }
            BeanUtil.copyProperties(businessObjectXml, businessObject);
            if(businessObject.getId()==null){
                businessObject.setId(IdUtil.getSuid());
                businessObjectManager.create(businessObject);
            }else{
                businessObjectManager.update(businessObject);
            }

            // 3. save table/column/ctrl
            for (BusTableXml busTableXml : businessObjectXml.getBusTableList()) {
                BusinessTable table = this.businessTableManager.getByKey(busTableXml.getKey());
                List<BusColumnXml> columnXmlList = busTableXml.getBusColumnList();
                Map<String, BusinessColumn> mapColumns = new HashMap();  //已有字段
                boolean isUpateTable = false;
                if (table == null) {
                    // new table
                    table = new BusinessTable();
                    BeanUtil.copyProperties(busTableXml, table);
                    table.setId(IdUtil.getSuid());
                    table.setCreateTime(new Date());
                    this.businessTableManager.create(table);
                    isUpateTable = false;
                } else {
                    // update table
                    isUpateTable = true;
                    BeanUtil.copyProperties(busTableXml, table);
                    table.setUpdateTime(new Date());
                    this.businessTableManager.update(table);
                    List<BusinessColumn> columnList = this.businessColumnManager.getByTableId(table.getId());
                    for (BusinessColumn column : columnList) {
                        // 添加已有字段
                        mapColumns.put(column.getKey(), column);
                    }
                }

                // 只考虑了增加和修改（假定无删除）
                for (BusColumnXml columnXml : columnXmlList) {
                    boolean addColumn = true;
                    String key = columnXml.getKey();
                    // 更新表且存在同key的字段
                    if (isUpateTable && mapColumns.containsKey(key)) {
                        addColumn = false;
                        BusinessColumn column = mapColumns.get(key);
                        // column
                        String columnId = column.getId();
                        BeanUtil.copyProperties(columnXml, column);
                        column.setId(columnId);
                        this.businessColumnManager.update(column);
                        // ctrl
                        JSONObject ctrlJson = JSON.parseObject(columnXml.getCtrJson());
                        if (ctrlJson == null) {
                            break;
                        }
                        BusColumnCtrl columnCtrl = JSON.toJavaObject(ctrlJson, BusColumnCtrl.class);
                        BusColumnCtrl columnCtrl2 = this.busColCtrlManager.getByColumnId(columnId);
                        if (columnCtrl2 != null) {
                            columnCtrl.setId(columnCtrl2.getId());
                            BeanUtil.copyProperties(columnCtrl, columnCtrl2);
                            columnCtrl2.setColumnId(column.getId());
                            this.busColCtrlManager.update(columnCtrl2);
                        } else {
                            columnCtrl.setColumnId(column.getId());
                            columnCtrl.setId(IdUtil.getSuid());
                            this.busColCtrlManager.create(columnCtrl);
                        }
                    }
                    if (addColumn) {
                        // column
                        BusinessColumn column = new BusinessColumn();
                        BeanUtil.copyProperties(columnXml, column);
                        column.setTableId(table.getId());
                        column.setId(IdUtil.getSuid());
                        this.businessColumnManager.create(column);
                        // ctrl
                        JSONObject ctrlJson = JSON.parseObject(columnXml.getCtrJson());
                        if (ctrlJson != null) {
                            BusColumnCtrl columnCtrl = JSON.toJavaObject(ctrlJson, BusColumnCtrl.class);
                            columnCtrl.setColumnId(column.getId());
                            columnCtrl.setId(IdUtil.getSuid());
                            this.busColCtrlManager.create(columnCtrl);
                        }
                    }
                }
            }
        }
    }

    private void fill(BusinessObject businessObject) {
        if (businessObject == null) {
            return;
        }

        for (BusTableRel rel : businessObject.getRelation().list()) {
            rel.setTable(this.businessTableManager.getFilledByKey(rel.getTableKey()));
            rel.setBusObj(businessObject);
        }

        handleSetParentRel(businessObject.getRelation());
    }


    private void handleSetParentRel(BusTableRel rel) {
        for (BusTableRel r : rel.getChildren()) {
            r.setParent(rel);
            handleSetParentRel(r);
        }
    }

}
